﻿using System;
using System.Collections.Generic;

namespace JyCommonKit.UndoRedoKit.CommandMode
{
    /// <summary>
    /// 撤销/还原管理器
    /// </summary>
    public class UndoRedoManager
    {
        /// <summary>
        /// 获取撤销还原单例
        /// </summary>
        /// <param name="name"> 某个撤销还原管理器 </param>
        /// <returns> 单例对象 </returns>
        public static UndoRedoManager GetInstance(string name)
        {
            UndoRedoManager manager;
            if (!_managers.TryGetValue(name, out manager))
            {
                manager = new UndoRedoManager();
                _managers.Add(name, manager);
            }

            return manager;
        }

        /// <summary>
        /// 是否可以撤销
        /// </summary>
        public bool IsCanUndo { get { return _undoList.Count > 0; } }

        /// <summary>
        /// 是否可以还原
        /// </summary>
        public bool IsCanRedo { get { return _redoList.Count > 0; } }

        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="command"> 需要执行的命令 </param>
        public void DoCommand(ICommand command)
        {
            if(command == null)
            {
                Console.WriteLine("DoCommand(ICommand command) command = null, Please check it.");
                return;
            }

            command.Execute();

            if(_undoList.Count >= _maxRecordCommandCnt)
            {
                _undoList.RemoveAt(0);
            }
            _undoList.Add(command);

            // 还原命令列表还有命令,这时执行新命令,则清空还原列表命令
            if (_redoList.Count > 0) _redoList.Clear();
        }

        /// <summary>
        /// 配置管理器
        /// </summary>
        /// <param name="maxRecordCommandCnt"> 最大记录数量 </param>
        public void ConfigManager(int maxRecordCommandCnt = 20)
        {
            _maxRecordCommandCnt = maxRecordCommandCnt;
        }

        /// <summary>
        /// 执行撤销操作
        /// </summary>
        public void Undo()
        {
            if(_undoList.Count == 0)
            {
                Console.WriteLine("The undo list is null!");
                return;
            }

            var endCnt = _undoList.Count - 1;
            var command = _undoList[endCnt];
            command.Undo();

            _undoList.RemoveAt(endCnt);

            if(_redoList.Count >= _maxRecordCommandCnt) _redoList.RemoveAt(0);
            _redoList.Add(command);
        }

        /// <summary>
        /// 执行还原操作
        /// </summary>
        public void Redo()
        {
            if(_redoList.Count == 0)
            {
                Console.WriteLine("The redo list is null!");
                return;
            }

            var endCnt = _redoList.Count - 1;
            var command = _redoList[endCnt];
            command.Execute();

            _redoList.RemoveAt(endCnt);

            if (_undoList.Count >= _maxRecordCommandCnt) _undoList.RemoveAt(0);
            _undoList.Add(command);
        }

        /// <summary>
        /// 清理所有命令
        /// </summary>
        public void Clear()
        {
            _undoList.Clear();
            _redoList.Clear();
        }

        /// <summary>
        /// 初始化
        /// </summary>
        private void Init()
        {
            _undoList = new List<ICommand>();
            _redoList = new List<ICommand>();
            ConfigManager();
        }

        private UndoRedoManager() { Init(); }

        /// <summary>
        /// 撤销列表
        /// </summary>
        private List<ICommand> _undoList;

        /// <summary>
        /// 还原列表
        /// </summary>
        private List<ICommand> _redoList;

        /// <summary>
        /// 最大记录命令数量
        /// </summary>
        private int _maxRecordCommandCnt;

        /// <summary>
        /// 静态管理器集合
        /// </summary>
        private static Dictionary<string, UndoRedoManager> _managers = new Dictionary<string, UndoRedoManager>();
    }
}
